动态规划与贪心算法的区别与联系

走出迷宫的人们,有的是认识路;有的是莽撞碰巧出来的;有的则是一路做着标记出来的;也有的是走遍了整个迷宫。
——证明了的贪心算法、没有证明的贪心算法、动态规划、暴力搜索的区别。

今天来谈谈经典的算法设计思路问题,涉及搜索(Searching),动态规划(DP, Dynamic Programming),贪心算法(GA, Greedy Algorithm)……至于什么回溯法(Backtracking)只能是搜索的方向问题。

经常听人说起:“搜索、动态规划、贪心算法这几种算法云云”,好像这些算法彼此之间并没有交集一样。

非也,它们的渊源大了!

从范畴上来看:

GreedyDPSearching

即,所有的贪心算法问题都能用DP求解,更可以归结为一个搜索问题,反之不成立

从动规到贪心

不管是动态规划还是贪心本质上都是一个搜索,这一点少有人发出疑问的。

然而却时常有人争论某问题是贪心的还是动归的,一个问题是贪心的还是动归的有联系但并不对立

看一个具体的例子:

食堂里有n个人要在一个队列里排队买饭,每个人花费的时间分别为 Ci ,求如何安排队列的顺序可以使得所有人的总用时最小,最小为多少?

比如有三个人,分别用时3,2,5,那么最佳的排序应该是2,3,5,总用时是2 + 5 + 10 = 17,对此,你可以简单地验证一下其他5种的组合来验证这个答案是正确的。

这个问题在暴力搜索算法中需要消耗O(n!)的时间来生成所有的排列并从中获得最小值。

也许我们需要优化一下……正常人略作思考便可以猜出让耗时短的人优先的贪心优化策略。

于是就有了这样一段代码(JavaScript),可以直接在现代浏览器的控制台内使用(推荐Chrome)。

var solve = C => {
    C.sort();
    var sum = 0;
    C.forEach((e, i) => sum += e * (C.length - i));
    return {
        min: sum,
        order: C
    };
}
solve([3, 2, 5]); // Object {min: 17, order: Array[3]}

这个问题的解空间是C数组的所有排列的集合,解空间的大小显然是O(n!)的,实际上其占用的存储空间是 O(nn!) 的,因为每个解都占用了O(n)的空间。然而其上的贪心算法并没有遍历解空间,因此这不是一个暴力搜索

由于任意顺序的C的所有排列的集合是一样的,因此他们的解空间与解都是一样的,所以我们直接把问题等价地化为经 O(nlogn) 的代价升序排列后的问题,即假设C已经有序。

设前 i 个人(已升序排列)能够达成的最小总用时为 f(i)

我们考虑把第i个人插入到前i-1个人的队列中去。

等等,我们是否能证明前i -1个人的最优排列也是前i个人最优排列的子排列(最优子结构的性质是否具备)?可以。假设前i人的最优排列不包含前i-1人的最优排列,则将除第i人外的人调整成前i-1人的序列可以更优,与假设矛盾,因此前i-1人的最优排列一定是前i人最优排列的子排列。

尝试将第i人插在第j人的前面,并考虑带来的影响,便有状态转移方程:

f(i)=f(i1)+minj[0,i]{ (ij)
  • 19
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值